#include "editorscene.h"
#include "material/particlematerial.h"
#include "material/terrainmatreial2.h"
#include "material/terrainmatreial.h"
#include "material/navigationhelpermaterial.h"
#include "material/linehelpermaterial.h"
#include "material/planehelpermaterial.h"
#include "material/gameobjectmaterial.h"
#include "shadowspace.h"

CEditorScene::CEditorScene(){
    m_rShadowSpace = NEW CShadowSpace();
    m_rShadowSpace->Init( 1024, 1024 );
    
    m_rTerrainMaterial = NEW CTerrainMaterial();
    m_rTerrainMaterial->Init();

    m_rNavigationHelperMaterial = NEW CNavigationHelperMaterial();
    m_rNavigationHelperMaterial->Init();

    m_rLineHelperMaterial = NEW CLineHelperMaterial();
    m_rLineHelperMaterial->Init();

    m_rPlaneHelperMaterial = NEW CPlaneHelperMaterial();
    m_rPlaneHelperMaterial->Init();

    m_rGameObjectMaterial = NEW CGameObjectMaterial();
    m_rGameObjectMaterial->Init();
    
    m_rParticleMaterial = NEW CParticleMaterial();
    m_rParticleMaterial->Init();

    m_rTerrainRenderElementManager = NEW CRenderElementManager();
    m_rNavigationHelperRenderElementManager = NEW CRenderElementManager();
    m_rLineHelperRenderElementManager = NEW CRenderElementManager();
    m_rPlaneHelperRenderElementManager = NEW CRenderElementManager();
    m_rGameObjectRenderElementManager = NEW CRenderElementManager();

    m_rParticleManager = NEW CMDXParticleManager( 1024, 64 );

    m_tFogColor.Set(255.0f / 255.0f, 255.0f / 255.0f, 255.0f / 255.0f, 1.0f);
    m_fFogNear = 4500.0f, m_fFogFar = 8000.0f;

    SetClearColor( 0.05f, 0.01f, 0.012f, 1.0f );
    //m_tAmbientLightColor.R = 1.0f, m_tAmbientLightColor.G = 1.0f, m_tAmbientLightColor.B = 1.0f, m_tAmbientLightColor.A = 1.0f;
    m_tLightColor.R = 1.8f, m_tLightColor.G = 1.8f, m_tLightColor.B = 1.8f, m_tLightColor.A = 1.0f;

    m_bTerrainVisibled = True;
    m_bTerrainLineHelperVisibled = True;
    m_bSceneObjectVisibled = True;
}
CEditorScene::~CEditorScene(){

}
bool32 CEditorScene::Final(){
    ////m_rTerrainRenderElementManager.Detach();
    //////m_rTerrainDecelRenderElementManager.Detach();
    //////m_rWaterRenderElementManager.Detach();
    ////m_rLineHelperRenderElementManager.Detach();
    ////m_rGameObjectRenderElementManager.Detach();
    ////m_rParticleManager.Detach();
    ClearAllChild();
    return True;
}
void CEditorScene::Update( int32 nDelta, float fDelta){
    CCamera* _pCamera = m_rCamera.GetEntityData();
    //m_pCamera->UpdateRenderList();
    //if( m_rSkyBox.IsAttached() ) m_rSkyBox->Update( &_pCamera->m_tPosition.X, nDelta, fDelta, _pCamera );
    _pCamera->UpdateRenderList();
    m_rTerrainRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );
    //m_rTerrainDecelRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );
    m_rNavigationHelperRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );

    m_rLineHelperRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );

    m_rPlaneHelperRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );
    //m_rWaterRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );
    m_rGameObjectRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );
    CScene::Update( nDelta, fDelta);

    ////float _fCameraPosX = _pCamera->m_tPosition.X;
    ////float _fCameraPosY = _pCamera->m_tPosition.Y;
    ////float _fCameraPosZ = _pCamera->m_tPosition.Z;

    ////float _fCameraViewPosX = _pCamera->m_tView.X;
    ////float _fCameraViewPosY = _pCamera->m_tView.Y;
    ////float _fCameraViewPosZ = _pCamera->m_tView.Z;
    ////m_rShadowSpace->Move( _fCameraViewPosX, _fCameraViewPosY, _fCameraViewPosZ );
    ////m_rShadowSpace->Update();

    Quaternion _sFixCameraQuat = {-0.5f,-0.5f,-0.5f,0.5f};
    Quaternion _cameraQuat;
    math_quat_multiply( _cameraQuat, m_rCamera->m_tQuaternion.m, _sFixCameraQuat );
    m_rParticleManager->Update( &_pCamera->m_tPosition.X, &_pCamera->m_tView.X, _cameraQuat, nDelta, fDelta );

}
void CEditorScene::Render( CTextureTarget* pTextureTarget, int32 nViewportWidth, int32 nViewportHeight ){
    Renderer_SetDepthTest(True);
    Renderer_SetDepthWrite(True);

    // shadow space
    m_rShadowSpace->BeginRender( nViewportWidth, nViewportHeight );
    m_rGameObjectRenderElementManager->RenderShadow();
    m_rShadowSpace->EndRender( );


    ////////////////////////////////////////////////////////////////////////////////////////////////
    // editor scene
    Renderer_SetDepthTest( True );
    Renderer_SetDepthWrite( True );
    pTextureTarget->BeginRender(nViewportWidth, nViewportHeight);
    Renderer_SetClearColor(m_tClearColor.R, m_tClearColor.G, m_tClearColor.B, m_tClearColor.A);
    Renderer_Clear(True, True);

    CCamera* _pCamera = m_rCamera.GetEntityData();
    Matrix3 _vNormalM;
    Math_Matrix3_GetNormalMatrix( _pCamera->m_tMatrixWorldInverse.m, _vNormalM );
    ////////////////////////////////////////////////////////////////////////////////////////////////
    //////////m_rSkyBoxMaterial->Begin();
    //////////m_rSkyBoxMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m);
    //////////if (m_rSkyBox.IsAttached())m_rSkyBox->Render();
    //////////m_rSkyBoxMaterial->End();

    ////////////////////////////////////////////////////////////////////////////////////////////////

    //float _vLightColor[3] = { 1.0,1.0,1.0 };
    CVector3 _vLightDirection= { -1.0f,1.0f,1.0f };
    CVector3 _vLightPositon = m_rShadowSpace->m_tPosition - m_rShadowSpace->n_tView;
    _vLightPositon.TransformDirection( &_pCamera->m_tMatrixWorldInverse, &_vLightDirection );


    if( m_bTerrainVisibled ){
        m_rTerrainMaterial->Begin();
        //m_rTerrainMaterial->SetProjectionMatrix( _pCamera->m_tProjectionMatrix.m );
        //m_rTerrainMaterial->SetViewMatrix( _pCamera->m_tMatrixWorldInverse.m );
        //m_rTerrainMaterial->SetNormalMatrix( _vNormalM );
        m_rTerrainMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m);
        //m_rTerrainMaterial->SetFogInfo( m_tFogColor.GetPointer(), m_fFogNear, m_fFogFar );
        //m_rTerrainMaterial->SetDiffuse( m_tAmbientLightColor.GetPointer() );
        //m_rTerrainMaterial->SetDirectionalLights_Direction( _vLightDirection );
        //m_rTerrainMaterial->SetDirectionalShadowMatrix( m_rShadowSpace->shadowMatrix.m );

        //m_rTerrainMaterial->SetDirectionalLights_Color( m_tLightColor.GetPointer() );
        //m_rTerrainMaterial->SetDirectionalShadowMap( 5, m_rShadowSpace->m_pTextureDepth->m_hTextureHandle );
        //m_rTerrainMaterial->SetDirectionalLights_ShadowInfo( m_rShadowSpace->m_fShadowBias, m_rShadowSpace->m_fShadowRadius, m_rShadowSpace->m_vShadowMapSize[0], m_rShadowSpace->m_vShadowMapSize[1] );

        m_rTerrainRenderElementManager->Render();
        m_rTerrainMaterial->End();
       ////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
       ////////////////////// m_rTerrainDecelMaterial->Begin();
       ////////////////////// m_rTerrainDecelMaterial->SetProjectionMatrix( _pCamera->m_tProjectionMatrix.m );
       ////////////////////// m_rTerrainDecelMaterial->SetViewMatrix( _pCamera->m_tMatrixWorldInverse.m );
       ////////////////////// m_rTerrainDecelMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m);
       ////////////////////// m_rTerrainDecelMaterial->SetNormalMatrix( _vNormalM );
       ////////////////////// m_rTerrainDecelMaterial->SetFogInfo( m_tFogColor.GetPointer(), m_fFogNear, m_fFogFar );
       ////////////////////// //m_rTerrainDecelMaterial->SetAmbientLightColor( m_tAmbientLightColor.GetPointer() );
       ////////////////////// m_rTerrainDecelMaterial->SetDirectionalLights_Direction( _vLightDirection );
       ////////////////////// m_rTerrainDecelMaterial->SetDirectionalShadowMatrix( m_rShadowSpace->shadowMatrix.m );
       ////////////////////// m_rTerrainDecelMaterial->SetDirectionalLights_Color( m_tLightColor.GetPointer() );
       ////////////////////// m_rTerrainDecelMaterial->SetDirectionalShadowMap( 5, m_rShadowSpace->m_pTextureDepth->m_hTextureHandle );
       ////////////////////// m_rTerrainDecelMaterial->SetDirectionalLights_ShadowInfo( m_rShadowSpace->m_fShadowBias, m_rShadowSpace->m_fShadowRadius, m_rShadowSpace->m_vShadowMapSize[0], m_rShadowSpace->m_vShadowMapSize[1] );

       ////////////////////// m_rTerrainDecelRenderElementManager->Render();
       ////////////////////// m_rTerrainDecelMaterial->End();


    }else{
        m_rNavigationHelperMaterial->Begin();
        m_rNavigationHelperMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m);
        m_rNavigationHelperRenderElementManager->Render();
        m_rNavigationHelperMaterial->End();
    }

    if( m_bTerrainLineHelperVisibled ){
        m_rLineHelperMaterial->Begin();
        m_rLineHelperMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m);
        m_rLineHelperRenderElementManager->Render();
        m_rLineHelperMaterial->End();
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////
    if( m_bSceneObjectVisibled ){
        m_rGameObjectMaterial->Begin();
        m_rGameObjectMaterial->SetProjectionMatrix( _pCamera->m_tProjectionMatrix.m);
        m_rGameObjectMaterial->SetViewMatrix( _pCamera->m_tMatrixWorldInverse.m);
        m_rGameObjectMaterial->SetNormalMatrix( _vNormalM );
        m_rGameObjectMaterial->SetFogInfo(m_tFogColor.GetPointer(), m_fFogNear, m_fFogFar);
        m_rGameObjectMaterial->SetDirectionalLights_Direction( _vLightDirection );
        m_rGameObjectMaterial->SetDirectionalLights_Color( m_tLightColor.GetPointer() );
        m_rGameObjectRenderElementManager->Render();
        m_rGameObjectMaterial->End();

        m_rParticleMaterial->Begin();
        m_rParticleMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m );
        m_rParticleMaterial->SetViewMatrix( _pCamera->m_tMatrixWorldInverse.m );
        m_rParticleManager->Render( m_rParticleMaterial.GetEntityData()  );
        m_rParticleMaterial->End();
    }

   ////////////////////// ////m_rRibbonMaterial->Begin();
   ////////////////////// ////m_rRibbonMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m );
   ////////////////////// ////m_rRibbonMaterial->End();

    ////////////////////////////////////////////////////////////////////////////////////////////////
    m_rPlaneHelperMaterial->Begin();
    m_rPlaneHelperMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m);
    m_rPlaneHelperRenderElementManager->Render();
    m_rPlaneHelperMaterial->End();


   ////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
   ////////////////////// m_rWaterMaterial->Begin();
   ////////////////////// m_rWaterMaterial->SetProjectionMatrix( _pCamera->m_tProjectionMatrix.m );
   ////////////////////// m_rWaterMaterial->SetViewMatrix( _pCamera->m_tMatrixWorldInverse.m );
   //////////////////////// m_rWaterMaterial->SetProjectionViewMatrix( m_pCamera->m_tProjScreenMatrix.m );
   ////////////////////// m_rWaterMaterial->SetFogInfo( m_tFogColor.GetPointer(), m_fFogNear, m_fFogFar );
   ////////////////////// m_rWaterRenderElementManager->Render();
   ////////////////////// m_rWaterMaterial->End();



    pTextureTarget->EndRender();

}

void CEditorScene::AddChild( CGameObject* pGameObject ){
    CScene::AddChild( pGameObject );
    switch( pGameObject->m_nGameObjectType ){
    case 0:{
        AddTerrainRenderElement(pGameObject);
    }break;
    case 1:{
        AddLineHelperRenderElement(pGameObject);
    }break;
    case 2:{
        AddSceneObjectRenderElement(pGameObject);
    }break;
    case 3:{
        AddPlaneHelperRenderElement(pGameObject);
    }break;
    case 4:{
        AddNavigationHelperRenderElement(pGameObject);
    }break;
    }
}

void CEditorScene::RemoveChild( CGameObject* pGameObject ){
    switch( pGameObject->m_nGameObjectType ){
    case 0:{
        RemoveTerrainRenderElement(pGameObject);
    }break;
    case 1:{
        RemoveLineHelperRenderElement(pGameObject);
    }break;
    case 2:{
        RemoveSceneObjectRenderElement(pGameObject);
    }break;
    case 3:{
        RemovePlaneHelperRenderElement(pGameObject);
    }break;
    case 4:{
        RemoveNavigationHelperRenderElement(pGameObject);
    }break;
    }

    CScene::RemoveChild( pGameObject );
}



void CEditorScene::AddTerrainRenderElement(CGameObject* pGameObject) {
    CRenderElement* _vRenderElementHandle[32];
    for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 32); i < n; i++) {
        CRenderElement* _pRenderElement = _vRenderElementHandle[i];
        _pRenderElement->m_pWorldM = pGameObject->m_vWorldM;
        _pRenderElement->m_pShadowMaterial = NULL;
        _pRenderElement->m_pMaterial = m_rTerrainMaterial.GetEntityData();
        m_rTerrainRenderElementManager->AddRenderElement( _pRenderElement );
    }
}
void CEditorScene::RemoveTerrainRenderElement(CGameObject* pGameObject) {
    if (pGameObject) {
        CRenderElement* _vRenderElementHandle[32];
        for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 32); i < n; i++) {
            CRenderElement* _hRenderHandle = _vRenderElementHandle[i];
            //m_pCamera->RemoveRenderElement(_hRenderHandle);
            m_rTerrainRenderElementManager->RemoveRenderElement( _hRenderHandle );
        }
    }
}
void CEditorScene::AddNavigationHelperRenderElement(CGameObject* pGameObject){
    CRenderElement* _vRenderElementHandle[2048];
    for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
        CRenderElement* _pRenderElement = _vRenderElementHandle[i];
        _pRenderElement->m_pWorldM = pGameObject->m_vWorldM;
        _pRenderElement->m_pShadowMaterial = NULL;
        _pRenderElement->m_pMaterial = m_rNavigationHelperMaterial.GetEntityData();
        m_rNavigationHelperRenderElementManager->AddRenderElement( _pRenderElement );
    }
}
void CEditorScene::RemoveNavigationHelperRenderElement(CGameObject* pGameObject){
    if (pGameObject) {
        CRenderElement* _vRenderElementHandle[2048];
        for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
            CRenderElement* _hRenderHandle = _vRenderElementHandle[i];
            m_rNavigationHelperRenderElementManager->RemoveRenderElement( _hRenderHandle );
        }
    }
}
void CEditorScene::AddLineHelperRenderElement( CGameObject* pGameObject ){
    CRenderElement* _vRenderElementHandle[2048];
    for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
        CRenderElement* _pRenderElement = _vRenderElementHandle[i];
        _pRenderElement->m_pWorldM = pGameObject->m_vWorldM;
        _pRenderElement->m_pShadowMaterial = NULL;
        _pRenderElement->m_pMaterial = m_rLineHelperMaterial.GetEntityData();
        m_rLineHelperRenderElementManager->AddRenderElement( _pRenderElement );
    }
}
void CEditorScene::RemoveLineHelperRenderElement( CGameObject* pGameObject ){
    if (pGameObject) {
        CRenderElement* _vRenderElementHandle[2048];
        for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
            CRenderElement* _hRenderHandle = _vRenderElementHandle[i];
            m_rLineHelperRenderElementManager->RemoveRenderElement( _hRenderHandle );
        }
    }
}
void CEditorScene::AddPlaneHelperRenderElement( CGameObject* pGameObject ){
    CRenderElement* _vRenderElementHandle[2048];
    for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
        CRenderElement* _pRenderElement = _vRenderElementHandle[i];
        _pRenderElement->m_pWorldM = pGameObject->m_vWorldM;
        _pRenderElement->m_pShadowMaterial = NULL;
        _pRenderElement->m_pMaterial = m_rPlaneHelperMaterial.GetEntityData();
        m_rPlaneHelperRenderElementManager->AddRenderElement( _pRenderElement );
    }
}
void CEditorScene::RemovePlaneHelperRenderElement( CGameObject* pGameObject ){
    if (pGameObject) {
        CRenderElement* _vRenderElementHandle[2048];
        for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
            CRenderElement* _hRenderHandle = _vRenderElementHandle[i];
            m_rPlaneHelperRenderElementManager->RemoveRenderElement( _hRenderHandle );
        }
    }
}
void CEditorScene::AddSceneObjectRenderElement(CGameObject* pGameObject){
    CRenderElement* _vRenderElementHandle[2048];
    for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
        CRenderElement* _pRenderElement = _vRenderElementHandle[i];
        _pRenderElement->m_pWorldM = pGameObject->m_vWorldM;
        _pRenderElement->m_pShadowMaterial = m_rShadowSpace->m_rShadowMaterial.GetEntityData();
        _pRenderElement->m_pMaterial = m_rGameObjectMaterial.GetEntityData();
        m_rGameObjectRenderElementManager->AddRenderElement( _pRenderElement );
    }
}
void CEditorScene::RemoveSceneObjectRenderElement(CGameObject* pGameObject){
    if (pGameObject) {
        CRenderElement* _vRenderElementHandle[2048];
        for (int32 i = 0, n = pGameObject->GetRenderElementHandles(_vRenderElementHandle, 2048); i < n; i++) {
            CRenderElement* _hRenderHandle = _vRenderElementHandle[i];
            m_rGameObjectRenderElementManager->RemoveRenderElement( _hRenderHandle );
        }
    }
}
